<template>
  <div class="root-container">
    <!-- Three.js渲染容器 -->
    <div ref="container" class="three-container"></div>

    <!-- 右侧固定信息展示框 -->
    <div class="info-panel">
      <div class="panel-header">
        <h3>设备信息</h3>
      </div>
      <div class="panel-content">
        <div v-if="hotLedgerCard" class="info-grid">
          <div class="info-item">
            <span class="label">设备名：</span>
            <p class="value">{{ hotLedgerCard.devicename }}</p>
          </div>
          <div class="info-item">
            <span class="label">设备位置描述：</span>
            <p class="value">{{ hotLedgerCard.devicelocationdesc }}</p>
          </div>
          <div class="info-item">
            <span class="label">蠕涨值/mm：</span>
            <span class="value">{{ hotLedgerCard.creepvalue }}</span>
          </div>
          <div class="info-item">
            <span class="label">测厚值/mm：</span>
            <span class="value">{{ hotLedgerCard.thicknessvalue }}</span>
          </div>
          <div class="info-item">
            <span class="label">厚度百分比：</span>
            <p class="value">
              {{ hotLedgerCard.thicknesspercentage || "暂无" }}
            </p>
          </div>
          <div class="info-item">
            <span class="label">记录类型：</span>
            <span class="value">{{ hotLedgerCard.recordtype || "暂无" }}</span>
          </div>
          <div class="info-item">
            <span class="label">管道材料：</span>
            <p class="value">{{ hotLedgerCard.pipematerial || "暂无" }}</p>
          </div>
          <div class="info-item">
            <span class="label">管材规格：</span>
            <p class="value">{{ hotLedgerCard.pipespecification || "暂无" }}</p>
          </div>
          <div class="info-item">
            <span class="label">宏观检查结果：</span>
            <p class="value">
              {{ hotLedgerCard.macroinspectionresult || "暂无" }}
            </p>
          </div>
          <div class="info-item">
            <span class="label">设备状态标记：</span>
            <span class="value">{{
              hotLedgerCard.devicestatusflag || "暂无"
            }}</span>
          </div>
          <div class="info-item">
            <span class="label">备注信息：</span>
            <p class="value">{{ hotLedgerCard.remark || "暂无" }}</p>
          </div>
          <div class="info-item">
            <span class="label">创建人：</span>
            <span class="value">{{ hotLedgerCard.creatorname || "暂无" }}</span>
          </div>
          <div class="info-item">
            <span class="label">修改人：</span>
            <span class="value">{{
              hotLedgerCard.modifiername || "暂无"
            }}</span>
          </div>
          <div class="info-item">
            <span class="label">检测日期：</span>
            <span class="value">{{
              hotLedgerCard.inspectiondate || "暂无"
            }}</span>
          </div>
          <!-- <div class="info-item">
            <span class="label">修改时间：</span>
            <span class="value">{{ hotLedgerCard.modifytime || "暂无" }}</span>
          </div> -->
        </div>
        <p v-else class="empty-tip">点击交互点查看设备信息</p>

        <div class="panel-footer" v-if="hotLedgerCard">
          <el-button type="primary" size="small" @click="viewHistoryLedger">
            查看往期台账
          </el-button>
        </div>
      </div>
    </div>

    <!-- 悬停提示框 -->
    <div
      class="tooltip"
      v-if="showTooltip"
      :style="{ left: `${tooltipPosition.x}px`, top: `${tooltipPosition.y}px` }"
    >
      {{ tooltipText }}
    </div>
  </div>
</template>
<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
export default {
  name: "HSX", // 后水悬吊管模型
  props: {
    // 接收从父组件传递的实模ID
    instanceId: {
      type: Number,
      default: null,
    },
  },
  data() {
    return {
      // DOM 引用与状态
      container: null,
      currentDeviceName: "", // 当前选中设备名称
      // 新增：交互相关ID
      pointId: null, // 基点ID
      deviceId: null, // 设备ID
      ledgerId: null, // 台账ID
      hotLedgerCard: null, // 台账卡片数据
      // 悬停提示相关
      showTooltip: false,
      tooltipText: "",
      tooltipPosition: { x: 0, y: 0 },
      // 交互点分类存储
      sootblowerInteractivePoints: [], // 吹灰器 (CH)
      pipelineInteractivePoints: [], // 管道 (GD)
      directionInteractivePoints: [], // 方位 (FX)
      allInteractivePoints: [], // 所有交互点集合
      // Three.js 核心对象
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      mixer: null,
      handleClick: null, // 点击事件处理函数
      handleMouseMove: null, // 鼠标移动事件处理函数
      // 初始相机状态
      initialCameraState: {
        position: new THREE.Vector3(5, 5, 5),
        target: new THREE.Vector3(0, 0, 0),
      },
    };
  },
  methods: {
    // 初始化 Three.js 场景
    initThree() {
      if (!this.container) {
        console.error("Three.js 容器 DOM 未找到，初始化终止");
        return;
      }
      // 创建场景、相机、渲染器
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0xf0f0f0);
      this.camera = new THREE.PerspectiveCamera(
        75,
        this.container.clientWidth / this.container.clientHeight,
        0.1,
        1000
      );
      this.camera.position.copy(this.initialCameraState.position);
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(
        this.container.clientWidth,
        this.container.clientHeight
      );
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.container.appendChild(this.renderer.domElement);
      // 添加轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.target.copy(this.initialCameraState.target);
      // 添加灯光
      this.scene.add(new THREE.AmbientLight(0xffffff, 0.5));
      const dirLight = new THREE.DirectionalLight(0xffffff, 1);
      dirLight.position.set(1, 1, 1);
      this.scene.add(dirLight);
      // 加载模型并处理交互点
      const loader = new GLTFLoader();
      loader.load(
        "/models/HSX001.glb",
        (gltf) => {
          this.scene.add(gltf.scene);
          // 遍历模型，筛选所有类型交互点
          gltf.scene.traverse((child) => {
            // 吹灰器交互点 (HSX_CH_*)
            if (child.name.match(/HSX_CH_(?:\d+[_-]\d+)/)) {
              this.sootblowerInteractivePoints.push(child);
              this.allInteractivePoints.push(child);
              this.addInteractiveMarker(child, 0x0066ff);
            }
            // 管道交互点 (HSX_GD_*)
            else if (child.name.match(/HSX_GD_\d+_\d+_null/)) {
              this.pipelineInteractivePoints.push(child);
              this.allInteractivePoints.push(child);
              this.addInteractiveMarker(child, 0x00cc66, 0.08);
            }
            // 方位交互点 (HSX_FX_*)
            else if (child.name.match(/HSX_FX_.+/)) {
              this.directionInteractivePoints.push(child);
              this.allInteractivePoints.push(child);
              this.addInteractiveMarker(child, 0xff6600);
            }
          });
          // 处理模型动画
          if (gltf.animations?.length) {
            this.mixer = new THREE.AnimationMixer(gltf.scene);
            gltf.animations.forEach((clip) =>
              this.mixer.clipAction(clip).play()
            );
          }
          // 初始化交互逻辑
          const raycaster = new THREE.Raycaster();
          const mouse = new THREE.Vector2();
          // 通用坐标转换方法
          const convertMousePosition = (event) => {
            const rect = this.container.getBoundingClientRect();
            mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
            mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
          };
          // 点击事件处理
          this.handleClick = (event) => {
            console.log(
              "点击事件触发，instanceId:",
              this.instanceId,
              "container:",
              this.container
            );
            if (!this.container || !this.instanceId) return;
            this.controls.update();
            convertMousePosition(event);
            // 射线检测
            raycaster.setFromCamera(mouse, this.camera);
            const intersects = raycaster.intersectObjects(
              this.allInteractivePoints,
              true
            );
            if (intersects.length > 0) {
              // 从相交对象获取交互点
              const sphere = intersects[0].object;
              const interactivePoint = sphere.parent;
              const deviceName = interactivePoint.name;
              this.currentDeviceName = deviceName;

              // 执行交互点点击逻辑链
              this.handleInteractivePointClick(deviceName);
            } else {
              console.warn("未命中任何交互点");
            }
          };
          // 鼠标移动（悬停）事件处理
          this.handleMouseMove = (event) => {
            if (!this.container) return;
            convertMousePosition(event);
            raycaster.setFromCamera(mouse, this.camera);
            const intersects = raycaster.intersectObjects(
              this.allInteractivePoints,
              true
            );
            if (intersects.length > 0) {
              // 显示悬停提示
              const sphere = intersects[0].object;
              const interactivePoint = sphere.parent;
              this.tooltipText = interactivePoint.name;
              this.showTooltip = true;
              // 设置提示框位置
              this.tooltipPosition = {
                x: event.clientX + 10,
                y: event.clientY - 20,
              };
            } else {
              this.showTooltip = false;
            }
          };
          // 绑定事件
          window.addEventListener("click", this.handleClick);
          window.addEventListener("mousemove", this.handleMouseMove);
          window.addEventListener("resize", this.handleResize);
          // 启动动画循环
          this.animate();
        },
        undefined,
        (error) => {
          console.error("模型加载失败:", error);
        }
      );
    },

    // 处理交互点点击的完整逻辑链
    handleInteractivePointClick(pointName) {
      // 重置之前的数据（仅在点击新交互点时重置）
      this.resetInteractiveData();
      this.loading = true;

      // 3.1 获取基点ID
      this.$api.modelBaseApi
        .queryBasePointId({ pointName: pointName })
        .then((res) => {
          if (res.data.code !== 1) {
            throw new Error("获取基点ID失败: " + (res.msg || "接口返回异常"));
          }
          this.pointId = res.data.data;
          console.log("获取基点ID成功:", this.pointId);

          // 3.2 获取设备ID
          return this.$api.modelInstanceModelsApi.queryDeviceId({
            instanceId: this.instanceId,
            pointId: this.pointId,
          });
        })
        .then((res) => {
          if (res.data.code !== 1) {
            throw new Error("获取设备ID失败: " + (res.msg || "接口返回异常"));
          }
          this.deviceId = res.data.data;
          console.log("获取设备ID成功:", this.deviceId);

          // 3.3 获取最新台账ID
          return this.$api.devLedgerApi.queryLatestLedgerId({
            deviceId: this.deviceId,
          });
        })
        .then((res) => {
          console.log("台账ID查询结果:", res);
          if (res.data.code === 1 && res.data.data) {
            // 有台账ID，继续请求台账卡片
            this.ledgerId = res.data.data;
            console.log("获取台账ID成功:", this.ledgerId);
            return this.$api.devLedgerApi.queryCardById({
              ledId: this.ledgerId,
            });
          } else {
            // 无台账ID，降级请求设备基础信息
            console.warn("无对应台账信息，降级请求设备基础数据");
            return this.$api.devDevicesApi.queryById({ id: this.deviceId });
          }
        })
        .then((res) => {
          this.loading = false;
          if (res.data.code === 1 && res.data.data) {
            // 区分是台账数据还是设备基础数据
            const data = res.data.data;
            if (data.deviceName) {
              // 设备基础数据格式映射（根据实际返回字段调整）
              this.hotLedgerCard = {
                devicename: data.deviceName, // 设备名（使用设备表字段）
                devicelocationdesc: data.deviceDesc, // 设备位置描述（使用设备表字段）
                creepvalue: "暂无此测点数据",
                thicknessvalue: "暂无此测点数据",
                thicknesspercentage: "暂无",
                recordtype: "暂无",
                pipematerial: data.pipeMaterial || "SA—210C", // 补充管道材料
                pipespecification: data.pipeSpecification || "Φ63.5×11", // 补充管道规格
                macroinspectionresult: "暂无",
                devicestatusflag: data.status === 3 ? "投用" : "未知", // 映射设备状态
                remark: "暂无",
                creatorname: "暂无",
                modifiername: "暂无",
                inspectiondate: "暂无",
                modifytime: data.updateTime || "暂无",
              };
            } else {
              // 正常台账数据直接赋值
              this.hotLedgerCard = {
                ...data,
                // 格式化日期显示
                inspectiondate: data.inspectiondate
                  ? this.formatDate(data.inspectiondate)
                  : "暂无",
                modifytime: data.modifytime
                  ? this.formatDate(data.modifytime)
                  : "暂无",
              };
            }
            console.log("最终展示数据:", this.hotLedgerCard);
          } else {
            throw new Error("数据获取失败: " + (res.msg || "接口返回异常"));
          }
        })
        .catch((error) => {
          this.loading = false;
          console.error("交互点处理失败:", error);
          this.$message.error("获取设备信息失败，请重试");
          // 仅在发生错误时重置数据，正常点击空白处不重置
          if (this.hotLedgerCard) {
            console.log("保持当前设备信息不变");
          } else {
            this.resetInteractiveData();
          }
        });
    },

    // 重置交互数据
    resetInteractiveData() {
      this.pointId = null;
      this.deviceId = null;
      this.ledgerId = null;
      this.hotLedgerCard = null;
    },

    formatDate(dateString) {
      if (!dateString) return "暂无";
      const date = new Date(dateString);
      return date.toLocaleString(); // 可根据需要调整格式
    },

    // 查看往期台账
    viewHistoryLedger() {
      // 可以跳转到台账列表页面或打开弹窗
      console.log("查看设备", this.deviceId, "的往期台账");
      // 示例: this.$router.push(`/ledgerList?deviceId=${this.deviceId}`);
    },

    // 添加交互点标记
    addInteractiveMarker(parent, color, radius = 0.15) {
      const sphere = new THREE.Mesh(
        new THREE.SphereGeometry(radius, 32, 32),
        new THREE.MeshBasicMaterial({
          color: color,
          transparent: true,
          opacity: 0.8,
        })
      );
      parent.add(sphere);
    },

    // 窗口大小调整处理
    handleResize() {
      if (!this.container) return;
      this.camera.aspect =
        this.container.clientWidth / this.container.clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(
        this.container.clientWidth,
        this.container.clientHeight
      );
    },

    // 动画循环
    animate() {
      requestAnimationFrame(() => this.animate());
      this.controls.update();
      if (this.mixer) this.mixer.update(0.016);
      this.renderer.render(this.scene, this.camera);
    },

    // 暴露给父组件的清理方法
    cleanupThreeResources() {
      // 1. 停止动画循环
      if (this.animationId) {
        cancelAnimationFrame(this.animationId);
        this.animationId = null;
      }

      // 2. 清理场景对象
      if (this.scene) {
        this.scene.traverse((child) => {
          // 清理几何体
          if (child.geometry) child.geometry.dispose();
          // 清理材质
          if (child.material) {
            if (Array.isArray(child.material)) {
              child.material.forEach((mat) => this.disposeMaterial(mat));
            } else {
              this.disposeMaterial(child.material);
            }
          }
        });
        this.scene.clear();
      }

      // 3. 清理渲染器和控制器
      if (this.renderer) {
        this.renderer.dispose();
        this.renderer.forceContextLoss(); // 强制释放WebGL上下文
        if (this.renderer.domElement && this.container) {
          this.container.removeChild(this.renderer.domElement);
        }
      }
      if (this.controls) {
        this.controls.dispose();
      }

      // 4. 清理动画混合器
      if (this.mixer) {
        this.mixer.stopAllAction();
        this.mixer = null;
      }

      // 5. 清空交互点和事件
      this.allInteractivePoints = [];
      this.sootblowerInteractivePoints = [];
      this.pipelineInteractivePoints = [];
      this.directionInteractivePoints = [];
      window.removeEventListener("click", this.handleClick);
      window.removeEventListener("mousemove", this.handleMouseMove);
      window.removeEventListener("resize", this.handleResize);

      // 6. 重置核心对象
      this.scene = null;
      this.camera = null;
      this.renderer = null;
      this.controls = null;
      this.container = null;
    },

    // 新增：清理材质及纹理
    disposeMaterial(mat) {
      mat.dispose();
      // 清理材质中的纹理
      for (const key in mat) {
        if (mat[key] && mat[key].isTexture) {
          mat[key].dispose();
        }
      }
    },

    // 修改动画循环方法，保存动画ID以便停止
    animate() {
      this.animationId = requestAnimationFrame(() => this.animate()); // 保存动画ID
      this.controls.update();
      if (this.mixer) this.mixer.update(0.016);
      this.renderer.render(this.scene, this.camera);
    },
  },
  watch: {
    // 监听实模ID变化，重新初始化交互
    instanceId(newVal) {
      console.log("实模ID变化:", newVal);
      // 可以根据需要重新加载模型或刷新交互
    },
  },
  mounted() {
    // 获取 DOM 引用后初始化
    this.container = this.$refs.container;
    this.initThree();
  },
  beforeUnmount() {
     this.cleanupThreeResources(); // 调用统一清理方法
     console.log("離開該頁面，已清理本頁面所有資源！");
     
  },
};
</script>
<style scoped>
.root-container {
  width: 100%;
  height: 100vh;
  position: relative;
  overflow: hidden;
}
.three-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
/* 右侧固定信息展示框样式 */
.info-panel {
  position: fixed;
  right: 20px;
  top: 50%;
  transform: translateY(-50%);
  width: 400px;
  max-height: 90vh;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(5px);
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
}
.panel-header {
  padding: 15px;
  border-bottom: 1px solid #eee;
}
.panel-header h3 {
  margin: 0;
  font-size: 16px;
  color: #333;
}
.panel-content {
  padding: 15px;
  flex: 1;
  overflow-y: auto;
}
.panel-footer {
  padding: 10px 15px;
  border-top: 1px solid #eee;
  text-align: right;
}
.empty-tip {
  color: #999;
  text-align: center;
  padding: 20px 0;
  margin: 0;
}
/* 信息网格布局 */
.info-grid {
  display: grid;
  grid-template-columns: 0.8fr 2.2fr;
  gap: 10px;
}
.info-item {
  padding: 5px 0;
  border-bottom: 1px dashed #f0f0f0;
}
.info-item:last-child {
  border-bottom: none;
}
.label {
  color: #666;
  font-size: 13px;
  font-weight: 500;
}
.value {
  color: #333;
  font-size: 13px;
  word-break: break-all;
}
/* 悬停提示框样式 */
.tooltip {
  position: fixed;
  padding: 5px 10px;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  border-radius: 4px;
  font-size: 12px;
  pointer-events: none;
  z-index: 1000;
  white-space: nowrap;
}
/* 滚动条样式优化 */
.panel-content::-webkit-scrollbar {
  width: 6px;
}
.panel-content::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}
.panel-content::-webkit-scrollbar-thumb {
  background: #ccc;
  border-radius: 3px;
}
.panel-content::-webkit-scrollbar-thumb:hover {
  background: #aaa;
}
</style>
